package main

import (
	"context"
	"fmt"
	demo "goim-pro/api/protos/example"
	protos "goim-pro/api/protos/salty"
	"goim-pro/examples/salty/contact"
	"goim-pro/examples/salty/group"
	"goim-pro/examples/salty/search"
	"goim-pro/examples/salty/user"
	"goim-pro/pkg/logs"
	"google.golang.org/grpc"
	"google.golang.org/grpc/keepalive"
	"log"
	"time"
)

const (
	//address = "47.102.149.231:9090"
	address = "127.0.0.1:9090"
)

var logger = logs.GetLogger("INFO")

func main() {
	//interceptor := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
	//	pb := req.(proto.Message)
	//	anyData, _ := utils.MarshalMessageToAny(pb)
	//	newReq := &protos.GrpcReq{
	//		DeviceId: "LOCAL_DEV",
	//		Version:  "",
	//		Language: 0,
	//		Os:       0,
	//		Token:    "",
	//		Data:     anyData,
	//	}
	//	err := invoker(ctx, method, newReq, reply, cc, opts...)
	//	return err
	//}
	var keepAlive = keepalive.ClientParameters{
		Time:                time.Second * time.Duration(30), // send pings every 30 seconds if there is no activity
		Timeout:             time.Second * time.Duration(5),  // wait 5 second for ping ack before considering the connection dead
		PermitWithoutStream: true,                            // send pings even without active streams
	}
	conn, err := grpc.Dial(
		address,
		grpc.WithInsecure(),
		grpc.WithKeepaliveParams(keepAlive),
		//grpc.WithUnaryInterceptor(interceptor)
	)
	if err != nil {
		log.Fatalf("grpc connect fail: %v", err)
	}
	defer conn.Close()

	exitChain := make(chan string)
	var str string
	go func() {
		for {
			_, _ = fmt.Scanln(&str)
			switch str {
			case "1":
				t := demo.NewWaiterClient(conn)
				req := demo.HelloReq{
					Name: "JAMES YANG",
				}
				resp, err := t.SayHello(context.Background(), &req)
				if err != nil {
					logger.Error(err)
				} else {
					logger.Info(resp)
				}
			case "s1":
				// create Writer service's client
				t := protos.NewSMSServiceClient(conn)
				for i := 1; i <= 3; i++ {
					user.ObtainSMSCode(t, protos.SMSOperationType_REGISTER, i)
				}
			case "s2":
				// create Writer service's client
				t := protos.NewSMSServiceClient(conn)
				user.ObtainSMSCode(t, protos.SMSOperationType_LOGIN, 3)
			case "s3":
				t := protos.NewSMSServiceClient(conn)
				user.ObtainSMSCode(t, protos.SMSOperationType_RESET_PASSWORD, 3)
			case "v1":
				t := protos.NewSMSServiceClient(conn)
				user.VerifyCode(t)
			case "rst1":
				t := protos.NewAccountServiceClient(conn)
				user.ResetPasswordByTelephone(t, "OLD_PASSWORD")
			case "rst2":
				t := protos.NewAccountServiceClient(conn)
				user.ResetPasswordByTelephone(t, "VERIFICATION")
			case "r":
				t := protos.NewAccountServiceClient(conn)
				for i := 1; i <= 3; i++ {
					time.Sleep(time.Second * 1)
					user.Register(t, i)
				}
			case "lt":
				t := protos.NewAccountServiceClient(conn)
				for i := 1; i <= 3; i++ {
					user.Login(t, "TELEPHONE", i)
				}
			case "lt2":
				t := protos.NewAccountServiceClient(conn)
				user.Login(t, "TELEPHONE", 3)
			case "lt3":
				t := protos.NewAccountServiceClient(conn)
				user.LoginWithCode(t, "TELEPHONE")
			case "le":
				t := protos.NewAccountServiceClient(conn)
				for i := 1; i <= 3; i++ {
					user.Login(t, "EMAIL", i)
				}
			case "lq":
				t := protos.NewAccountServiceClient(conn)
				user.Logout(t)
			case "gu":
				t := protos.NewUserServiceClient(conn)
				user.GetUserInfo(t)
			case "qt":
				t := protos.NewUserServiceClient(conn)
				user.QueryUserInfo(t, "TELEPHONE")
			case "qe":
				t := protos.NewUserServiceClient(conn)
				user.QueryUserInfo(t, "EMAIL")
			case "ud":
				t := protos.NewUserServiceClient(conn)
				user.UpdateUserInfo(t)

			// contacts
			case "ct-rq":
				t := protos.NewContactServiceClient(conn)
				contact.RequestContact(t)
			case "ct-acp":
				t := protos.NewContactServiceClient(conn)
				contact.AcceptContact(t)
			case "ct-rf":
				t := protos.NewContactServiceClient(conn)
				contact.RefusedContact(t)
			case "ct-udt":
				t := protos.NewContactServiceClient(conn)
				contact.UpdateRemarkInfo(t)
			case "ct-fa":
				t := protos.NewContactServiceClient(conn)
				contact.GetContactList(t)
			case "ct-nf":
				t := protos.NewContactServiceClient(conn)
				contact.GetContactOperationList(t)
			case "ct-rm":
				t := protos.NewContactServiceClient(conn)
				contact.DeleteContact(t)
			// search
			case "sh1":
				t := protos.NewSearchServiceClient(conn)
				search.Search(t, protos.SearchType_USER, "13631210001")
			case "sh2":
				t := protos.NewSearchServiceClient(conn)
				search.Search(t, protos.SearchType_CONTACT, "JAMES")
			case "sh3":
				t := protos.NewSearchServiceClient(conn)
				search.Search(t, protos.SearchType_GROUP, "xxx")
			case "sha":
				t := protos.NewSearchServiceClient(conn)
				search.Search(t, protos.SearchType_ALL, "13631210001")
			// groups
			case "gp-cre":
				t := protos.NewGroupServiceClient(conn)
				group.CreateGroup(t)
			case "gp-fa":
				t := protos.NewGroupServiceClient(conn)
				group.GetGroups(t)
			// exit
			case "q":
				logger.Infoln("grpc client disconnected!")
				exitChain <- str
			default:
				logger.Info("server continue to listen...")
			}
			logger.Info("********************************************")
		}
	}()

	toolsIntroduce()

	_ = <-exitChain
	logger.Info("grpc server exit!")
}

func toolsIntroduce() {
	logger.Info("********************************************")
	logger.Info("**** Welcome to [GRPC] client tools ****")
	logger.Info("**** Can input the commons to test ****")
	logger.Info("** ['1']: sayHello **")
	logger.Info("** ['s1']: obtainSMSCode - register**")
	logger.Info("** ['s2']: obtainSMSCode - login**")
	logger.Info("** ['s3']: obtainSMSCode - resetPassword**")
	logger.Info("** ['v1']: verifySMSCode - login**")
	logger.Info("** ['rst1']: resetPassword by telephone with oldPassword**")
	logger.Info("** ['rst2']: resetPassword by telephone with verification**")
	logger.Info("** ['r']: register **")
	logger.Info("** ['lt']: login by telephone **")
	logger.Info("** ['lt2']: login by telephone with diff deviceId **")
	logger.Info("** [lt3]: login by telephone with sms code **")
	logger.Info("** ['le']: login by email **")
	logger.Info("** ['lq']: user logout **")
	logger.Info("** ['gu']: get user info by userId **")
	logger.Info("** ['qt']: query user info by telephone **")
	logger.Info("** ['qe']: query user info by email **")
	logger.Info("** ['ud']: update user profile **")

	logger.Info("** *********************** **")
	logger.Info("** ['ct-rq']: request add contact **")
	logger.Info("** ['ct-acp']: accept add contact **")
	logger.Info("** ['ct-rf']: refused contact request **")
	logger.Info("** ['ct-rm']: delete contact **")
	logger.Info("** ['ct-udt']: update contact remark profile **")
	logger.Info("** ['ct-fa']: get all contacts **")
	logger.Info("** ['ct-nf']: get all notification messages **")

	logger.Info("** *********************** **")
	logger.Info("** ['sh1']: search users **")
	logger.Info("** ['sh2']: search contacts **")
	logger.Info("** ['sh3']: search groups **")
	logger.Info("** ['sha']: search all **")

	logger.Info("** *********************** **")
	logger.Info("** ['gp-cre']: create new group **")
	logger.Info("** ['gp-fa']: get all groups **")

	logger.Info("** ['q']: exist [GRPC] client **")
}
